/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client;

import DAL.Account;
import DAL.Album;
import DAL.DAL;
import DAL.Imageupload;
import common.ImageUtil;
import common.MessageType;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.List;
import javax.imageio.ImageIO;

/**
 *
 * @author Mr Bao
 */
public class Client implements Runnable {

    private Socket socket;
    private OutputStream out;
    private InputStream in;
    private boolean isRuning = true;
    private DAL d;
    private int userId = -1;
    private Account account;
    private List<Album> albums;
    private Album album;
    private List<Imageupload> imageuploads;
    private int indexImage;

    public Client(Socket socket, DAL d) {
        this.socket = socket;
        this.d = d;
        try {
            in = socket.getInputStream();
            out = socket.getOutputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        new Thread(this).start();
    }

    private void Close() {
        try {
            in.close();
            out.close();
            socket.close();
            isRuning = false;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void SendMessage(String message) {
        try {
            out.write(message.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
            Close();
        }
    }

    public void run() {
        while (isRuning) {
            try {
                int lenght = in.available();
                if (lenght > 0) {
                    byte[] data = new byte[lenght];
                    int count = in.read(data);
                    while (count < lenght) {
                        count += in.read(data, count, lenght - count);
                    }
                    String message = new String(data);
                    System.out.println(message);
                    String[] messages = message.split(":");
                    if (messages[0].equals(MessageType.Message)) {
                    } else if (messages[0].equals(MessageType.UploadImage)) {
                        int n = Integer.parseInt(messages[1]);
                        String formatImage = messages[2];
                        int albumId = Integer.parseInt(messages[3]);
                        byte[] images = new byte[n];
                        int c = in.read(images);
                        while (c < n) {
                            c += in.read(images, c, n - c);
                        }
                        ImageUtil.SaveImage(images, formatImage, d, albums.get(albumId));
                    } else if (messages[0].equals(MessageType.Login)) {
                        Login(messages[1], messages[2]);
                    } else if (messages[0].equals(MessageType.Register)) {
                        Register(messages[1], messages[2]);
                    } else if (messages[0].equals(MessageType.ListAlbum)) {
                        SendListAlbum();
                    } else if (messages[0].equals(MessageType.ViewImage)) {
                        SendImage(Integer.parseInt(messages[1]));
                    } else if (messages[0].equals(MessageType.CreateAlbum)) {
                        CreateAlbum(messages[1]);
                    } else if (messages[0].equals(MessageType.ViewListImage)) {
                        SendListImage(Integer.parseInt(messages[1]));
                    } else if (messages[0].equals(MessageType.NewUpload)) {
                        SendNewUpload();
                    } else if (message.equals(MessageType.Exit)) {
                        Close();
                        return;
                    } else if (messages[0].equals(MessageType.ListImageName)) {
                        SendListImageName(Integer.parseInt(messages[1]));
                    } else if (message.equals(MessageType.ViewImageNext)) {
                        SendImageNext();
                    } else if (message.equals(MessageType.ViewImagePre)) {
                        SendImagePre();
                    }
                }
                System.gc();
            } catch (Exception e) {
                e.printStackTrace();
                Close();
            }
        }
    }

    private void CreateAlbum(String albumName) {
        try {
            Album albumNew = new Album();
            albumNew.setName(albumName);
            albumNew.setDateCreate(new Date());
            albumNew.setIsDelete(false);
            albumNew.setUserId(userId);
            d.Insert(albumNew);
        } catch (Exception e) {
            e.printStackTrace();
            Close();
        }
    }

    private void Login(String username, String password) {
        account = d.Login(username, password);
        if (account != null) {
            userId = account.getId();
        } else {
            userId = -1;
        }
        SendMessage(MessageType.Login + ":" + userId);
    }

    private void Register(String username, String password) {
        SendMessage(MessageType.Register + ":" + d.Register(username, password));
    }

    private void SendListAlbum() {
        try {
            albums = d.GetAllAlbumByUserId(userId);
            String content = MessageType.ListAlbum;
            for (int i = 0; i < albums.size(); i++) {
                content += ":" + albums.get(i).getName();
            }
            content += ":END";
            SendMessage(content);
        } catch (Exception ex) {
            ex.printStackTrace();
            Close();
        }
    }

    private void SendImage(int index) {
        try {
            Imageupload imageupload = imageuploads.get(index);
            BufferedImage originalImage = ImageIO.read(new File(imageupload.getNameFile()));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(originalImage, "png", baos);
            baos.flush();
            byte[] imageInByte = baos.toByteArray();
            baos.close();
            String message = MessageType.ViewImage + ":" + imageInByte.length;
            System.out.println(message);
            out.write(message.getBytes());
            Thread.sleep(200);
            out.write(imageInByte);
            indexImage = index;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void SendListImageName(int index) {
        try {
            album = albums.get(index);
            imageuploads = d.GetAllImageuploads(album.getId());

            int count = 0;
            for (int i = 0; i < imageuploads.size(); i++) {
                String str = MessageType.ListImageName + ":";
                str += imageuploads.get(i).getName().substring(imageuploads.get(i).getName().toString().indexOf("/"));
                out.write(str.getBytes());
                Thread.sleep(500);
                count++;
                if (count > 20) {
                    break;
                }
            }
            Thread.sleep(1000);
            out.write((MessageType.EndImage).getBytes());
        } catch (Exception e) {
            e.printStackTrace();
            Close();
        }
    }

    private void SendListImage(int index) {
        try {
            album = albums.get(index);
            imageuploads = d.GetAllImageuploads(album.getId());
            for (int i = 0; i < imageuploads.size(); i++) {
                Imageupload imageupload = imageuploads.get(i);
                BufferedImage originalImage = ImageIO.read(new File(imageupload.getNameFile()));
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(originalImage, "png", baos);
                baos.flush();
                byte[] imageInByte = baos.toByteArray();
                baos.close();
                String message = MessageType.Image + ":" + imageInByte.length;
                System.out.println(message);
                out.write(message.getBytes());
                Thread.sleep(200);
                out.write(imageInByte);
                Thread.sleep(3000);
            }
            Thread.sleep(2000);
            out.write((MessageType.EndImage).getBytes());
        } catch (Exception e) {
            e.printStackTrace();
            Close();
        }
    }

    private void SendImageNext() {
        if (indexImage < imageuploads.size() - 1) {
            SendImage(indexImage + 1);
        } else {
            SendImage(0);
        }
    }

    private void SendImagePre() {
        if (indexImage > 0) {
            SendImage(indexImage - 1);
        } else {
            SendImage(imageuploads.size() - 1);
        }
    }

    private void SendNewUpload() {
        try {
            imageuploads = d.GetNewImageUpload();
             int count = 0;
            for (int i = 0; i < imageuploads.size(); i++) {
                String str = MessageType.ListImageName + ":";
                str += imageuploads.get(i).getName().substring(imageuploads.get(i).getName().toString().indexOf("/"));
                out.write(str.getBytes());
                Thread.sleep(500);
                count++;
                if (count > 20) {
                    break;
                }
            }
            Thread.sleep(1000);
            out.write((MessageType.EndImage).getBytes());
        } catch (Exception e) {
            e.printStackTrace();
            Close();
        }
    }
}
